Skip to content

PUMAS round3#357

Open
cacraigucar wants to merge 65 commits into
ESCOMP:mainfrom
nusbaume:pumas_round3
Open

PUMAS round3#357
cacraigucar wants to merge 65 commits into
ESCOMP:mainfrom
nusbaume:pumas_round3

Conversation

@cacraigucar

@cacraigucar cacraigucar commented Jan 16, 2026

Copy link
Copy Markdown
Collaborator

Originator(s): cacraigucar, nusbaume, billsacks, peverwhee, I-Kuan Hu, jimmielin

Description (include issue title and the keyword ['closes', 'fixes', 'resolves'] and issue number):

  • PUMAS code now has metadata and goes through the CAM-SIMA compilation step. [Note PUMAS diagnostics will come in a later stage] - This step has been named "round3".
  • This commit contains contributions from participants at the PUMAS hackathon
  • Partially addresses CCPP-ize PUMAS #118

List all namelist files that were added or changed:
A schemes/pumas/pumas_pre_main_namelist.xml
- pumas CAM-SIMA namelist generator

List all files eliminated and why: N/A

List all files added and what they do:
A schemes/pumas/micro_pumas_ccpp_dimensions_post.F90
A schemes/pumas/micro_pumas_ccpp_dimensions_post.meta
A schemes/pumas/micro_pumas_ccpp_dimensions_pre.F90
A schemes/pumas/micro_pumas_ccpp_dimensions_pre.meta
- code which subsets and converts to pumas_r8 and back

A schemes/pumas/pumas_pre_main.F90
A schemes/pumas/pumas_pre_main.meta
A schemes/pumas/pumas_post_main.F90
A schemes/pumas/pumas_post_main.meta
- placeholder for interstitial schemes

A schemes/sima_diagnostics/pumas_diagnostics.F90
A schemes/sima_diagnostics/pumas_diagnostics_calling.F90
A schemes/sima_diagnostics/pumas_diagnostics.F90-keep_for_run
- These are being included even though they are only partially complete - NO REVIEW IS BEING DONE NOW

A test/test_suites/suite_pumas.xml
- test suite for PUMAS

A schemes/microp_aero/ccpp/hetfrz_classnuc_stub.F90
A schemes/microp_aero/ccpp/hetfrz_classnuc_stub.meta
A schemes/microp_aero/ccpp/hetfrz_classnuc_stub_namelist.xml
- stub for hetfrz_classnuc to provide the namelist option do_hetfrz_classnuc used by PUMAS core (micro_pumas_ccpp)

A schemes/pumas/micro_pumas_ccpp_optics_limiter.F90
A schemes/pumas/micro_pumas_ccpp_optics_limiter.meta
- optics property limiter for strat_cldfrc<cldfrc_min copied from micro_pumas_cam

A schemes/utilities/clamp_number_concentrations.F90
A schemes/utilities/clamp_number_concentrations.meta
- clamp number concentrations to 1e-12, 1e10 range the same as CAM physics types

A test/test_schemes/clubb_stub.F90
A test/test_schemes/clubb_stub.meta

List all existing files that have been modified, and describe the changes:
(Helpful git command: git diff --name-status development...<your_branch_name>)
M .gitmodules
M doc/NamesNotInDictionary.txt
M schemes/pumas/pumas

M schemes/rasch_kristjansson/rk_stratiform.F90
M schemes/rasch_kristjansson/rk_stratiform.meta
M schemes/rrtmgp/rrtmgp_lw_cloud_optics.meta
M schemes/rrtmgp/rrtmgp_sw_cloud_optics.meta
M schemes/sima_diagnostics/rk_stratiform_diagnostics.F90
M schemes/sima_diagnostics/rk_stratiform_diagnostics.meta
M test/test_schemes/initialize_constituents.F90
- updated standard names

List all automated tests that failed, as well as an explanation for why they weren't fixed:

Is this an answer-changing PR? If so, is it a new physics package, algorithm change, tuning change, etc?
- new capability in CAM-SIMA

If yes to the above question, describe how this code was validated with the new/modified features:

@cacraigucar
cacraigucar marked this pull request as draft January 16, 2026 21:11
@cacraigucar
cacraigucar requested a review from nusbaume June 18, 2026 21:38
@cacraigucar
cacraigucar marked this pull request as ready for review June 18, 2026 21:38
@jimmielin

Copy link
Copy Markdown
Collaborator

Please note that since compute_cloud_fraction_two_moment has been merged, rhmini in micro_pumas_ccpp can now use its value via the namelist and the hardcoded value in registry.xml for CAM-SIMA can also be removed. Please see nusbaume/PUMAS#1

jimmielin and others added 20 commits July 14, 2026 16:39
… pumas_post_main

Mirrors CAM micro_pumas_cam post-call recomputation, which discards the
per-substep values PUMAS returns. Match dei standard name with RRTMGP and
the CAM-SIMA registry (singular crystal). Run pumas_post_main before
apply_heating_rate (air density uses the pre-heating temperature) and add
the low stratiform cloud fraction optics limiter to the suite.
Mirrors CAM micro_pumas_cam, including the separate meters-to-microns
conversion step. Match snow diameter standard name with RRTMGP and the
CAM-SIMA registry (snow_crystal).
Updates for bit-for-bit fields that interact with RRTMGP
atmos_phys0_26_000: Move ndrop_bam, nucleate_ice, and other microp_aero interstitials to atmos_phys (ESCOMP#411)
@nusbaume

Copy link
Copy Markdown
Collaborator

Automated code review (PR #357 — PUMAS round3)

This is an AI-assisted review (claude-opus:4.8) against the rules in doc/Code-review.md, doc/Code-style.md, and AGENTS.md. Per the PR description, pumas_diagnostics.F90 and pumas_diagnostics_calling.F90 are explicitly not being reviewed at this stage, so I've excluded them (I did note a couple of things about them at the bottom for later). Auto-generated doc/NamesNotInDictionary.txt and the submodule pointer/.gitmodules bumps were not reviewed.

High priority

  1. Missing implicit noneschemes/pumas/micro_pumas_ccpp_dimensions_post.F90 (Code-style MUST). The module preamble goes straight from the use statements to public :: with no implicit none. Every module must have implicit none in the preamble.

  2. errmsg must be character(len=*), not character(len=512) (Code-review rule 11). The rule explicitly covers CCPP-framework variables such as errmsg. This affects:

    • schemes/pumas/micro_pumas_ccpp_dimensions_pre.F90 (both subroutines)
    • schemes/pumas/micro_pumas_ccpp_dimensions_post.F90
    • schemes/pumas/micro_pumas_ccpp_optics_limiter.F90
    • schemes/pumas/pumas_pre_main.F90 (both subroutines)
    • schemes/pumas/pumas_post_main.F90
    • schemes/utilities/clamp_number_concentrations.F90 (both subroutines)
    • test/test_schemes/clubb_stub.F90

    For reference, schemes/microp_aero/ccpp/hetfrz_classnuc_stub.F90 (added in this same PR) already does this correctly with character(len=*).

  3. Module-level saveschemes/utilities/clamp_number_concentrations.F90:13 (Code-review rule 1). Module variables are implicitly saved, so the explicit module-level save is redundant and should be removed.

Medium priority

  1. endifend if (Code-review rule 4)schemes/pumas/pumas_pre_main.F90:46 (the if (do_clubb_sgs) block).

  2. Commented-out code (Code-review rule 13) — schemes/utilities/clamp_number_concentrations.F90. The _run subroutine ends with a large block of commented-out alternative implementation (the q_projected = ... formulation, ~30 lines). The explanatory rationale is valuable, but per rule 13 the dead code itself should be removed (keep the explanation as prose if you want the reasoning preserved). Note this also leaves the declared local q_projected unused in the active code.

  3. Namelist XML missing the standard comment block (Code-review rule 6). Neither new namelist file has the standard <!-- Each namelist variable is defined in an <entry> element... --> block that follows <entry_id_pg version="2.0"> in the other namelist XMLs (e.g. dadadj_namelist.xml):

    • schemes/microp_aero/ccpp/hetfrz_classnuc_stub_namelist.xml
    • schemes/pumas/pumas_pre_main_namelist.xml
  4. Missing default private + explicit public (Code-style: modules are default private with explicit public interfaces).

    • schemes/pumas/micro_pumas_ccpp_dimensions_pre.F90 (no private, no public)
    • schemes/pumas/micro_pumas_ccpp_dimensions_post.F90 (has public but no private)
    • schemes/pumas/pumas_pre_main.F90 (no private, no public)

Low priority / for human review

  1. Comment grammar/typo (Code-review rule 9) — schemes/pumas/pumas_pre_main.F90 header. "The hope that there will eventually be one set of portable interstitials..." is a sentence fragment (missing "is" — "The hope is that..."), and "intersititals" is misspelled (→ "interstitials").

  2. schemes/sima_diagnostics/pumas_diagnostics.F90-keep_for_run (2150 lines added). This file has a non-.F90 extension and appears to be a leftover working/backup copy committed by accident (GitHub can't even diff it). It falls under the diagnostics work you've flagged as out-of-review, but a -keep_for_run file almost certainly should not be committed to the repo — please confirm/remove.

  3. (Optional, Code-review rule 3 — pure.) The pure data-reshaping converters do no I/O and have no side effects, so they are candidates for the pure keyword: micro_pumas_ccpp_dimensions_pre_*, micro_pumas_ccpp_dimensions_post_run, micro_pumas_ccpp_optics_limiter_run, and clamp_number_concentrations_run. (pumas_post_main_run calls external size_dist_param_* routines, so it likely can't be pure.) Flagging as optional since it isn't universal practice for CCPP entry points here.

  4. (Minor, Code-style modern syntax.) schemes/utilities/clamp_number_concentrations.F90:~112 uses the old array-constructor (/ ... /); prefer [ ... ].

Notes (not blocking)

  • The effective_radius_of_stratiform_cloud_{liquid_water,ice}_particle..._droplet/..._crystal and effective_diameter_..._particle_for_radiation..._crystal_for_radiation renames are applied consistently across rk_stratiform.{F90,meta}, rrtmgp_{lw,sw}_cloud_optics.meta, and rk_stratiform_diagnostics.{F90,meta}, with units unchanged (um). No rule-14 (same standard_name, differing units) conflicts were found in the modified .meta files.
  • The new mass_number_concentration_*_{droplets,drops,crystals,particles}_in_moist_air_and_condensed_water names in initialize_constituents.F90 are consistent with their use in clamp_number_concentrations.F90. As a reminder (AGENTS.md), any newly coined standard names should be explicitly called out in the PR description for SE review.
  • For later: pumas_diagnostics.F90 and pumas_diagnostics_calling.F90 also carry module-level save statements (rule 1) — worth addressing when those files come up for review.

@nusbaume nusbaume left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting all of the required interstitials set up @cacraigucar and @jimmielin! I have some comments and change requests, but I believe many should either be easy to fix, or can just be pushed off onto future work issues (including the standard name requests). Of course if you have any questions or concerns just let me know!


!CCPP error handling:
character(len=*), intent(out) :: errmsg
integer, intent(out) :: errcode

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix indentation here to better align with the code above?

Suggested change
integer, intent(out) :: errcode
integer, intent(out) :: errcode

Comment on lines +85 to +96
!Host model dimensions/parameters:
integer, intent(in) :: ncol
integer, intent(in) :: nlev
integer, intent(in) :: nlevp1
integer, intent(in) :: trop_cloud_top_lev !Index of the top model level for which
!cloud physics is applied (1 to nlev)

!PUMAS dimensions/parameters:
integer, intent(in) :: micro_ncol !Number of horizontal microphysics columns (count)
integer, intent(in) :: micro_nlev !Number of microphysics vertical layers (count)
integer, intent(in) :: micro_nlevp1 !Number of microphysics vertical interfaces (count)
integer, intent(in) :: micro_dust_nbins !Number of dust bins

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like most of these variables aren't used in this subroutine, so I think this can be cleaned up to be the following:

Suggested change
!Host model dimensions/parameters:
integer, intent(in) :: ncol
integer, intent(in) :: nlev
integer, intent(in) :: nlevp1
integer, intent(in) :: trop_cloud_top_lev !Index of the top model level for which
!cloud physics is applied (1 to nlev)
!PUMAS dimensions/parameters:
integer, intent(in) :: micro_ncol !Number of horizontal microphysics columns (count)
integer, intent(in) :: micro_nlev !Number of microphysics vertical layers (count)
integer, intent(in) :: micro_nlevp1 !Number of microphysics vertical interfaces (count)
integer, intent(in) :: micro_dust_nbins !Number of dust bins
!Host model dimensions/parameters:
integer, intent(in) :: ncol
integer, intent(in) :: trop_cloud_top_lev !Index of the top model level for which
!cloud physics is applied (1 to nlev)

Comment on lines +3 to +4
use pumas_kinds, only: pumas_r8=>kind_r8
use ccpp_kinds, only: kind_phys

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been caught by the AI, but can we move these use statements down to the relevant subroutine level?

advected = true
[pumas_cldliq]
standard_name = pumas_cloud_liquid_water_mixing_ratio_wrt_moist_air_and_condensed_water
long_name = microphysics cloud liquid wrt moist air and condensed water of new state

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might add "mixing ratio" to the long name here:

Suggested change
long_name = microphysics cloud liquid wrt moist air and condensed water of new state
long_name = microphysics cloud liquid mixing ratio wrt moist air and condensed water of new state

[pumas_frzimm]
standard_name = tendency_of_pumas_cloud_liquid_droplet_number_concentration_due_to_immersion_freezing
long_name = microphysics tendency of cloud liquid droplet number concentration due to immersion freezing
units = cm-3

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why I didn't catch this earlier, but essentially by definition a variable that is a tendency_of_X must have a s-1 term in the units, which it looks like the three frz variables listed here don't have.

I wouldn't worry about it for this PR, but it might be good to create an issue pointing out this discrepency, as it could potentially indicate either a science bug or an incorrect description of what the variable actually is.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note to feel free to assign this issue to me as I will deal with the units when CCPPizing hetfrz_classnuc eventually, beyond the MAM work.

@@ -0,0 +1,1206 @@
[ccpp-table-properties]
name = micro_pumas_ccpp_dimensions_post
type = scheme

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need a dependencies and kind_spec attribute here?

Suggested change
type = scheme
type = scheme
dependencies = pumas/pumas_kinds.F90
kind_spec = pumas_kinds:pumas_r8=>kind_r8

kind = pumas_r8
intent = in
[numice_tend]
standard_name = tendency_of_mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should say cloud_ice_water_crystals:

Suggested change
standard_name = tendency_of_mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water
standard_name = tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_wrt_moist_air_and_condensed_water

Comment on lines +98 to +110
rho(:,:) = real(pmid(:ncol,:), pumas_r8) / &
(real(rair, pumas_r8) * real(temp(:ncol,:), pumas_r8))
icwmrst(:,:) = min(real(cldliq(:ncol,:), pumas_r8) / &
max(mincld, real(strat_cldfrc(:ncol,:), pumas_r8)), 0.005_pumas_r8)
ncic(:,:) = real(numliq(:ncol,:), pumas_r8) / &
max(mincld, real(strat_cldfrc(:ncol,:), pumas_r8))

mu(:,:) = 0._pumas_r8
lambdac(:,:) = 0._pumas_r8
do k = trop_cloud_top_lev, nlev
call size_dist_param_liq(mg_liq_props, icwmrst(:,k), ncic(:,k), rho(:,k), &
mu(:,k), lambdac(:,k), ncol)
end do

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be a science bug here, in that the rho is calculated using the dry air gas constant and regular temperature (but the full pressure), and is then being used to convert the value of various mass number concentration variables (like ncic), which is with respect to the mass of moist air and condensed water. I obviously wouldn't worry about fixing it here, but might be worth opening an issue so that we can double-check it in the future?

Also pinging @PeterHjortLauritzen in case I am totally wrong here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note that I think this bug belongs to ESCOMP/PUMAS.

The post-interstitial rho is consistent with the one inside micro_pumas_v1.F90

        rho(i,k) = p(i,k)/(r*t(i,k))

p here is also pmid, r is rair

The rho cancels out in des and degrau, I think, so it's just pgam and lamc.

If a fix is made it should be in PUMAS then the downstream interstitials are adjusted to remain consistent. This would introduce answer changes everywhere, though.

Comment on lines +3 to +4
type = scheme
dependencies = pumas/micro_pumas_utils.F90

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the kind-related dependencies here as well?

Suggested change
type = scheme
dependencies = pumas/micro_pumas_utils.F90
type = scheme
dependencies = pumas/micro_pumas_utils.F90
dependencies = pumas/pumas_kinds.F90
kind_spec = pumas_kinds:pumas_r8=>kind_r8

intent = in
advected = true
[numice]
standard_name = mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should be cloud_ice_water_crystals here:

Suggested change
standard_name = mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water
standard_name = mass_number_concentration_of_cloud_ice_water_crystals_wrt_moist_air_and_condensed_water

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants